package com.koron.standard.rating.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.koron.common.core.business.common.entity.TOrderNoMax;
import com.koron.common.core.business.common.service.TOrderNoMaxService;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.standard.bean.base.BaseBean;
import com.koron.standard.bean.query.PageQuery;
import com.koron.standard.deviceClasssify.bean.po.Type;
import com.koron.standard.deviceClasssify.service.TypeService;
import com.koron.standard.rating.bean.dto.RatingDTO;
import com.koron.standard.rating.bean.dto.RatingExcel;
import com.koron.standard.rating.bean.po.Rating;
import com.koron.standard.rating.bean.po.RatingItem;
import com.koron.standard.rating.bean.query.RatingQuery;
import com.koron.standard.rating.bean.vo.RatingVO;
import com.koron.standard.rating.mapper.RatingMapper;
import com.koron.standard.utils.CommonUtils;
import com.koron.standard.utils.StandardCodeTools;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 评级标准(Rating)表服务实现类
 *
 * @author jzp
 * @since 2022-01-04
 */
@Service
public class RatingService extends ServiceImpl<RatingMapper, Rating> {
    @Autowired
    RatingItemService ratingItemService;

    @Autowired
    TypeService typeService;

    @Autowired
    TOrderNoMaxService tOrderNoMaxService;

    public QueryWrapper<RatingVO> queryWrapper(RatingQuery query) {
        // 设置默认只查有权限的水司数据
        query.setAppids(CommonUtils.getDefaultAppids(query.getAppids()));
        query.setPublicStatus(CommonUtils.getDefaultPublicStatus(query.getPublicStatus()));

        QueryWrapper<RatingVO> wrapper = new QueryWrapper<>();
        wrapper.like(StrUtil.isNotEmpty(query.getCode()), "c_rating.code", query.getCode());
        wrapper.like(StrUtil.isNotEmpty(query.getName()), "c_rating.name", query.getName());
        wrapper.eq(StrUtil.isNotEmpty(query.getTypeId()), "c_rating.type_id", query.getTypeId());
        wrapper.like(StrUtil.isNotEmpty(query.getTypeName()), "c_type.name", query.getTypeName());

        if (query.getPublicStatus() != null && query.getPublicStatus() > 0) {
            // 如果是共有的
            wrapper.and(w -> w.eq("c_rating.public_status", query.getPublicStatus())
                    .or(CollUtil.isNotEmpty(query.getAppids()))
                    .in(CollUtil.isNotEmpty(query.getAppids()), "c_rating.appid", query.getAppids()));
        } else {
            wrapper.in(CollUtil.isNotEmpty(query.getAppids()), "c_rating.appid", query.getAppids());
        }

        wrapper.eq(query.getStatus()!=null, "c_rating.status", query.getStatus());
        wrapper.eq(StrUtil.isNotEmpty(query.getDeptId()), "c_rating.dept_id", query.getDeptId());
        wrapper.like(StrUtil.isNotEmpty(query.getDeptName()), "c_rating.dept_name", query.getDeptName());
        if (CollUtil.isNotEmpty(query.getDates())) {
            wrapper.between("c_rating.create_time", query.getDates().get(0), query.getDates().get(1));
        }
        wrapper.eq("c_rating.delete_flag", 0);
        return wrapper;
    }

    public List<RatingVO> list(RatingQuery query) {
        QueryWrapper<RatingVO> wrapper = queryWrapper(query);
        return getBaseMapper().selectPageVo(wrapper);
    }

    public Page<RatingVO> page(PageQuery<RatingVO> pageQuery, RatingQuery query) {
        QueryWrapper<RatingVO> wrapper = queryWrapper(query);
        Page<RatingVO> page = pageQuery.convertPage();
        List<OrderItem> orders = pageQuery.getOrders();
        for (OrderItem order : orders) {
            if (order.getColumn().equals("type_name")) {
                order.setColumn("c_type.name");
            } else if (order.getColumn().equals("app_name")) {
                order.setColumn("s_app.name");
            } else {
                order.setColumn("c_rating." + order.getColumn());
            }
        }
        getBaseMapper().selectPageVo(page, wrapper);
        return page;
    }

    /**
     * 导出数据查询
     */
    public List<RatingExcel> listExcel(RatingQuery query) {
        // 1. 查询主表数据
        List<RatingVO> list = list(query);
        if (list == null) {
            return new ArrayList<>();
        }
        // 2. 查询从表数据
        List<RatingItem> ratingItems = ratingItemService.listByRatingIds(list.stream().map(BaseBean::getId).collect(Collectors.toList()));
        // <raingId, ratingItems>
        Map<String, List<RatingItem>> ratingItemMap = ratingItems.stream().collect(Collectors.groupingBy(RatingItem::getRatingId));
        return list.stream().map(ratingVO -> {
            RatingExcel ratingExcel = BeanUtil.toBean(ratingVO, RatingExcel.class);
            List<RatingItem> ratingItemList = ratingItemMap.get(ratingVO.getId());
            // <类别1，2，3，4 : 内容>
            Map<String, String> itemMap = ratingItemList.stream().collect(Collectors.toMap(RatingItem::getName, RatingItem::getContent, (o1, o2) -> o1));
            ratingExcel.setFirst(itemMap.get("1"));
            ratingExcel.setSecond(itemMap.get("2"));
            ratingExcel.setThree(itemMap.get("3"));
            ratingExcel.setFour(itemMap.get("4"));
            return ratingExcel;
        }).collect(Collectors.toList());
    }

    public RatingDTO getDtoById(String id) {
        RatingVO ratingVO = getBaseMapper().getVoById(id);
        RatingDTO ratingDTO = new RatingDTO();
        BeanUtils.copyProperties(ratingVO, ratingDTO);
        List<RatingItem> items = ratingItemService.listByRatingId(id);
        ratingDTO.setItems(items);
        return ratingDTO;
    }

    public void saveDto(RatingDTO ratingDTO) {
        // 设置编码
        ratingDTO.setCode(StandardCodeTools.getRatingCode());

        // 默认草稿
        ratingDTO.setStatus(0);

        // 保存
        updateDtoById(ratingDTO);

    }

    @Transactional(rollbackFor = RuntimeException.class)
    public void updateDtoById(RatingDTO ratingDTO) {
        // 1. 删除所有子项
        ratingItemService.removeByRatingId(ratingDTO.getId());

        // 2. 保存或更新基本信息
        saveOrUpdate(ratingDTO);

        // 3. 保存子项信息
        List<RatingItem> checks = Optional.ofNullable(ratingDTO.getItems()).orElse(new ArrayList<>());
        int i = 0;
        for (RatingItem check : checks) {
            check.setRatingId(ratingDTO.getId());
            check.setSort(i++);
        }
        ratingItemService.saveBatch(checks);

    }

    public void updateToPublic(List<String> ids) {
        List<Rating> ratings = new ArrayList<>();
        for (String id : ids) {
            Rating rating = new Rating();
            rating.setId(id);
            rating.setPublicStatus(1);
            ratings.add(rating);
        }
        updateBatchById(ratings);
    }

    public void updateStatus(String id, Integer status) {
        LambdaUpdateWrapper<Rating> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Rating::getId, id);
        wrapper.set(Rating::getStatus, status);
        update(wrapper);
    }

    /**
     * 导入数据
     * @param readAll 设备分类编码	设备分类名称	一类标准	二类标准	三类标准	四类标准
     */
    public void importFile(List<Map<String, Object>> readAll) {
        Assert.notEmpty(readAll, "数据不能为空");
        List<Type> types = typeService.listByIds(readAll.stream().map(e -> e.get("设备分类ID").toString().trim()).collect(Collectors.toList()));

        // 1. 插入评级标准
        // 1.1 获取当天最大编码
        TOrderNoMax maxNo = tOrderNoMaxService.peekNoMax(StandardCodeTools.ratingPrefix, null, types.size());
        String prefix = StandardCodeTools.ratingPrefix + maxNo.getDate();
        AtomicInteger atomicInteger = new AtomicInteger(maxNo.getMaxValue() - types.size());

        // 1.2 获取水司id
        String appId = ThreadLocalContext.get().getAppId();
        // 1.3 默认公共
        Integer publicStatus = 0;
        // 1.4 默认发布
        Integer status = 0;
        // 1.5 构造评级标准list
        List<Rating> ratings = types.stream().map(e -> {
            Rating rating = new Rating();
            rating.setCode(prefix + String.format("%0" + 3 + "d", atomicInteger.getAndIncrement()));
            rating.setName(e.getName() + "评级标准");
            rating.setTypeId(e.getId());
            rating.setTypeCode(e.getCode());
            rating.setAppid(appId);
            rating.setStatus(status);
            rating.setPublicStatus(publicStatus);
            return rating;
        }).collect(Collectors.toList());
        // 1.6 批量保存评级标准list
        saveBatch(ratings);

        // 2. 构造设备分类ID和评级标准id的map
        Map<String, String> codeMap = ratings.stream().collect(Collectors.toMap(Rating::getTypeId, Rating::getId, (o1, o2) -> o1));

        // 2.1 构造RatingItem
        List<RatingItem> ratingItems = new ArrayList<>();
        readAll.forEach(e -> {
            String ratingId = codeMap.get(e.get("设备分类ID").toString().trim());
            ratingItems.add(RatingItem.builder()
                    .ratingId(ratingId)
                    .name("1")
                    .content(e.get("一类标准").toString().trim())
                    .sort(1)
                    .build());
            ratingItems.add(RatingItem.builder()
                    .ratingId(ratingId)
                    .name("2")
                    .content(e.get("二类标准").toString().trim())
                    .sort(2)
                    .build());
            ratingItems.add(RatingItem.builder()
                    .ratingId(ratingId)
                    .name("3")
                    .content(e.get("三类标准").toString().trim())
                    .sort(3)
                    .build());
            ratingItems.add(RatingItem.builder()
                    .ratingId(ratingId)
                    .name("4")
                    .content(e.get("四类标准").toString().trim())
                    .sort(4)
                    .build());
        });

        ratingItemService.saveBatch(ratingItems);
    }
}
